﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Graphexcersize
{
    class BasicGraph : IBasicGraph
    {
        private Dictionary<Vertex, int> dTable; //Distance table
        private Dictionary<Vertex, string> rTable;  // route table
        private List<Vertex> q; //List of unvisited vertices
        private List<Vertex> vList; // List of all vertices
        private List<Edge> eList;  // List of all edges

        public BasicGraph()
        {
            vList = new List<Vertex>();
            eList = new List<Edge>();
            rTable = new Dictionary<Vertex, string>();
            dTable = new Dictionary<Vertex, int>();
        }

        public List<Edge> EList
        {
            get { return eList; }
            set { eList = value; }
        }
        
        
        public List<Vertex> VList
        {
            get { return vList; }
            set { vList = value; }
        }


        public void AddVertex(Vertex vertex)
        {
            //Vertex v = new Vertex();
           vList.Add(vertex);
        }

        public void RemoveVertex(Vertex vertex)
        {
            vList.Remove(vertex);
        }

        public void AddEdge(Edge edge)
        {
            //Edge = new Edge();
            eList.Add(edge);
        }

        public void RemoveEdge(Edge edge)
        {
            eList.Remove(edge);
        }

        public List<Vertex> AdjacentVertexes(Vertex vertex)
        {
            List<Vertex> l = new List<Vertex>();
            foreach(Edge e in eList)
            {
                if(e.V1.Equals(vertex))
                    l.Add(e.V2);
                if(e.V2.Equals(vertex) && e.Direction == false)
                    l.Add(e.V1);   
            }
            return l;
        }

        public Dictionary<Vertex, int> ShortestPath(Vertex start)
        {
            q = vList;
            FillTables(start);
            while(q.Count>0)
            {
                Vertex v = FindLowest();
                LoopEdges(v);
            }
            //Console.WriteLine("Afrejsested: " + start.Name);
            //foreach (KeyValuePair<Vertex, int> entry in dTable)
            //{
            //    Console.WriteLine("Destination: " + entry.Key.Name + "    Afstand: " + entry.Value);
            //}
            return dTable; 
        }

        private void FillTables(Vertex start)
        {
            dTable.Clear();
            rTable.Clear();
            foreach (Vertex v in vList)
            {
                rTable.Add(v, "empty");
                if(v.Equals(start))
                {
                    dTable.Add(v, 0);
                }   
                else
                {
                    dTable.Add(v, 1000000);
                }
            }
        }

        private Vertex FindLowest()
        {
            Vertex v = null;
            int w = 0;
            foreach(KeyValuePair<Vertex, int> entry in dTable)
            {
                if(q.Contains(entry.Key))
                {
                    if(v==null)
                    {
                        v = entry.Key;
                        w = entry.Value;
                    }
                    else
                    {
                        if(w > entry.Value)
                        {
                            v = entry.Key;
                            w = entry.Value;
                        }
                    }
                }
            }
            if(v!=null)
                q.Remove(v);
            return v;
        }

        private void LoopEdges(Vertex v)
        {
            foreach (Edge e in eList)
            {
                if (v.Equals(e.V1))
                {
                    if (dTable[v] + e.Weight < dTable[e.V2])
                    {
                        dTable[e.V2] = dTable[v] + e.Weight;
                        rTable[e.V2] = e.V1.Name;
                    }
                }
                else
                {
                    if (v.Equals(e.V2))
                    {
                        if (dTable[v] + e.Weight < dTable[e.V1])
                        {
                            dTable[e.V1] = dTable[v] + e.Weight;
                            rTable[e.V1] = e.V2.Name;
                        }
                    }
                }
            } 
        }
    }
}
